package modeler;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.vecmath.Tuple2f;
import javax.vecmath.Vector2f;
import javax.vecmath.Vector3f;

import modeler.shape.Mesh;
import modeler.shape.Shape;
import javax.media.opengl.GL;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.*;

/**
 * This class is a swing widget that will display the OpenGL implementation of
 * what is going on in the modeler.
 *
 * @author ags
 */
public class GLView extends JPanel implements GLEventListener {
        //changed?
       
        //GUI element names
        private static final String WIREFRAME_CHECKBOX_TEXT = "Wireframe";
        private static final String LIGHTING_CHECKBOX_TEXT = "Lighting";
  private static final String FLIP_CHECKBOX_TEXT = "Camera Flip";
       
        static final long serialVersionUID = 1L;
       
        //GUI parameters
        private final int[] viewport = new int[4];
        protected boolean drawInPickMode = false;
        protected boolean multiPickMode = false;
        protected boolean wireframe = false;
        protected boolean lighting = true;
       
        //added
        public static boolean drawInPickVertMode= false;
 
        //GUI elements
        protected GLCanvas canvas;
        protected Camera camera;
        protected GLAxes axes;
        protected EventHandler handler;
        protected JTree transformationTreeView;
        protected MainFrame mainFrame;
 
  //Current number of polygons in the scene
  public static int polyCount = 0;
 
 
  public static int currentObjectId = -1;
  public static int currentVertexId = -1;
  public static Vector3f currentVertex = null;
  public static Vector3f currentVertex2 = null;
  Mesh currentMesh = null;
  public static Transformation currentT=null;
 
 
        /**
         * Create a OpenGL drawing panel
         * @param newMainFrame
         * @param newTransformationTreeView
         * @param newCamera
         */
        public GLView(MainFrame newMainFrame, JTree newTransformationTreeView, Camera newCamera) {
                handler = new EventHandler();
                camera = newCamera;
                axes = new GLAxes();
                mainFrame = newMainFrame;
                transformationTreeView = newTransformationTreeView;
               
                GLCapabilities capabilities = new GLCapabilities();
                capabilities.setDoubleBuffered(true);
                canvas = new GLCanvas(capabilities);
                canvas.addGLEventListener(this);
               
                setLayout(new BorderLayout());
                add(canvas, BorderLayout.CENTER);
                add(createTopPanel(), BorderLayout.NORTH);
               
                canvas.addMouseListener(handler);
                canvas.addMouseMotionListener(handler);
               
                setMinimumSize(new Dimension(250, 250));
        }
       
        /**
         * Initialize the wireframe and lighting boxes in the panel
         * @return
         */
        protected JComponent createTopPanel() {
               
                JPanel toReturn = new JPanel(new BorderLayout());
                toReturn.add(new JLabel(" " + camera), BorderLayout.WEST);
               
                JPanel temp = new JPanel(new GridLayout(1, 3));
               
    JCheckBox flipBox = new JCheckBox(FLIP_CHECKBOX_TEXT, false);
    flipBox.addActionListener(handler);
    temp.add(flipBox);
                JCheckBox wireBox = new JCheckBox(WIREFRAME_CHECKBOX_TEXT, wireframe);
                wireBox.addActionListener(handler);
                temp.add(wireBox);
                JCheckBox lightBox = new JCheckBox(LIGHTING_CHECKBOX_TEXT, lighting);
                lightBox.addActionListener(handler);
                temp.add(lightBox);
               
                toReturn.add(temp, BorderLayout.EAST);
                toReturn.add(new JPanel(), BorderLayout.CENTER);
                return toReturn;
        }
       
        /**
         * Toggle the vertex/object pick mode.
         * @void
         */
        public static void togglePickMode() {
                drawInPickVertMode = !drawInPickVertMode;
        }
       
        /**
         * Getter for camera
         * @return
         */
        public Camera getCamera() {
               
                return camera;
               
        }
       
        /**
         * Setter for camera
         * @param newCamera
         */
        public void setCamera(Camera newCamera) {
               
                camera = newCamera;
        }
       
        /**
         * @see javax.media.opengl.GLEventListener#displayChanged(javax.media.opengl.GLAutoDrawable, boolean, boolean)
         */
        public void displayChanged(GLAutoDrawable d, boolean arg1, boolean arg2) {
               
                refresh();
               
        }
       
        /**
         * Repaints the canvas
         *
         */
        public void refresh() {
               
                canvas.repaint();
               
        }
       
        /**
         * @see javax.media.opengl.GLEventListener#init(javax.media.opengl.GLAutoDrawable)
         */
        public void init(GLAutoDrawable d) {
               
                GL gl = d.getGL();
                gl.glDepthFunc(GL.GL_LESS);
                gl.glEnable(GL.GL_DEPTH_TEST);
                gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
                gl.glEnable(GL.GL_BLEND);
                gl.glEnable(GL.GL_NORMALIZE);
               
                gl.glLightModeli(GL.GL_LIGHT_MODEL_COLOR_CONTROL, GL.GL_SEPARATE_SPECULAR_COLOR);
                gl.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, new float[] { 0.1f, 0.1f, 0.1f }, 0);
                gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, GL.GL_TRUE);
                gl.glLightModeli(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_TRUE);
                gl.glClearColor(0.2f, 0.2f, 0.2f, 1);
                gl.glShadeModel(GL.GL_SMOOTH);
               
                gl.glSelectBuffer(mainFrame.pickBuffer.capacity(), mainFrame.pickBuffer);
        }
       
        /**
         * Choosing pick or regular via flag is necessary
         * because all drawable calls must be made from
         * the AWT event thread (i.e., start at display())
         * @see javax.media.opengl.GLEventListener#display(javax.media.opengl.GLAutoDrawable)
         */
        public void display(GLAutoDrawable d) {
               
                GL gl = canvas.getGL();
                GLU glu = new GLU();

    if (drawInPickMode) {
                        gl.glRenderMode(GL.GL_SELECT);
                       
                        gl.glViewport(0, 0, canvas.getWidth(), canvas.getHeight());
                        gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
                       
                        // Never wireframe
                        gl.glCullFace(GL.GL_BACK);
                        gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL);
                       
                        // Camera and pick projections
                        gl.glMatrixMode(GL.GL_PROJECTION);
                        gl.glLoadIdentity();
                        glu.gluPickMatrix(handler.lastMousePixel_X, (canvas.getHeight() - 1) - handler.lastMousePixel_Y, 6, 6, viewport, 0);
                        camera.doProjection(canvas);
                       
                        // Camera lookat
                        gl.glMatrixMode(GL.GL_MODELVIEW);
                        gl.glLoadIdentity();
                        camera.doModelview(canvas);
                       
                        gl.glInitNames();
                        gl.glPushName(1); // push a dummy name onto the stack so we can call
                        // glLoadName from now on
                       
                        // Render only pickable items
                        synchronized (transformationTreeView) {
                                TreeModel transformationTree = transformationTreeView.getModel();
                                SceneNode root = (SceneNode) (transformationTree.getRoot());
                                polyCount = root.render(gl, glu);
                                mainFrame.updatePolyCount();
                        }
                       
                        if (mainFrame.currentManip != null)
                                mainFrame.currentManip.renderConstantSize(d, camera);
                       
                        // Stop pick mode
                        drawInPickMode = false;
                       
                        // Process hits
                        processHits(gl.glRenderMode(GL.GL_RENDER));
               
                }else {
                        displaySetup();
                        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
                        gl.glViewport(0, 0, canvas.getWidth(), canvas.getHeight());
                       
                        gl.glMatrixMode(GL.GL_PROJECTION);
                        gl.glLoadIdentity();
                        camera.doProjection(canvas);
                       
                        gl.glMatrixMode(GL.GL_MODELVIEW);
                        gl.glLoadIdentity();
                        camera.doModelview(canvas);
                       
                        synchronized (transformationTreeView) {
                                TreeModel transformationTree = transformationTreeView.getModel();
                                SceneNode root = (SceneNode) (transformationTree.getRoot());
                               
                                drawLights(root, camera, gl, glu);
                               
                                polyCount = root.render(gl, glu);
                                mainFrame.updatePolyCount();
                        }
                       
                        drawGrid(gl);
                       
                        axes.renderConstantSize(d, camera);
                        if (mainFrame.currentManip != null)
                                mainFrame.currentManip.renderConstantSize(d, camera);
                }
        }
       
public void displayVerts(Mesh m) {
               
                GL gl = canvas.getGL();
                GLU glu = new GLU();

                        gl.glRenderMode(GL.GL_SELECT);
                       
                        gl.glViewport(0, 0, canvas.getWidth(), canvas.getHeight());
                        gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
                       
                        // Never wireframe
                        gl.glCullFace(GL.GL_BACK);
                        gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL);
                       
                        // Camera and pick projections
                        gl.glMatrixMode(GL.GL_PROJECTION);
                        gl.glLoadIdentity();
                        glu.gluPickMatrix(handler.lastMousePixel_X, (canvas.getHeight() - 1) - handler.lastMousePixel_Y, 20, 20, viewport, 0);
                        camera.doProjection(canvas);
                       
                        // Camera lookat
                        gl.glMatrixMode(GL.GL_MODELVIEW);
                        gl.glLoadIdentity();
                        camera.doModelview(canvas);
                       
                        gl.glInitNames();
                        gl.glPushName(1); // push a dummy name onto the stack so we can call
                        // glLoadName from now on
                       
                        gl.glMatrixMode(GL.GL_MODELVIEW);
                        gl.glPushMatrix();
                       
                        RenderVerts(m);
                       
                        gl.glMatrixMode(GL.GL_PROJECTION);
                        gl.glPopMatrix();
                        gl.glMatrixMode(GL.GL_MODELVIEW);
                        //added
                        gl.glPopMatrix();
                       
                        int hits = gl.glRenderMode(GL.GL_RENDER);
                       
                        // Process hits
                        processVertHits(hits, mainFrame.pickBuffer, m);
               
                       
                        // Stop pick mode
                        drawInPickMode = false;
        }

       
       
        /**
         * Draws the lights
         * @param root
         * @param camera2
         * @param gl
         * @param glu
         */
        private void drawLights(SceneNode root, Camera camera, GL gl, GLU glu) {
               
                for (int i=0; i<root.getChildCount(); i++) {
                        SceneNode node = (SceneNode)root.getChildAt(i);
                        if (node instanceof Light) {
                                Light light = (Light)node;
                                light.draw(gl, glu, camera);
                        }
                }
               
        }
       
  /**
   * Setup all the lights
   * @param gl
   */
        protected void lightSetup(GL gl) {
                TreeModel transformationTree = transformationTreeView.getModel();
                SceneNode root = (SceneNode) (transformationTree.getRoot());
               
                for (int i=0; i<root.getChildCount(); i++) {
                        SceneNode node = (SceneNode)root.getChildAt(i);
                        if (node instanceof Light) {
                                Light light = (Light)node;
                                gl.glLightfv(light.id, GL.GL_POSITION, light.position, 0);
                                gl.glLightfv(light.id, GL.GL_DIFFUSE, light.diffuse, 0);
                                gl.glLightfv(light.id, GL.GL_AMBIENT, light.ambient, 0);
                                gl.glLightfv(light.id, GL.GL_SPECULAR, light.specular, 0);
                        }
                }
        }
       
        /**
         * Set the culling, wireframe, and lighting paramters based on current settings
         */
        protected void displaySetup() {
               
                GL gl = canvas.getGL();
                if (wireframe) {
                        gl.glCullFace(GL.GL_BACK);
                        gl.glDisable(GL.GL_CULL_FACE);
                        gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE);
                }
                else {
                        gl.glCullFace(GL.GL_BACK);
                        gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL);
                }
               
                if (lighting) {
                        gl.glEnable(GL.GL_LIGHTING);
      Light.turnOnLights(gl);
      lightSetup(gl);
                }
                else {
                        gl.glDisable(GL.GL_LIGHTING);
                }
        }
       
        /**
         * Handle the picking events
         * @param numHits
         */
        public void processHits(int numHits) {
               
                boolean picked = false;
                // Give hitting manipulators first priority
                for (int i_hit = 0; i_hit < numHits; i_hit++) {
                        int idx = i_hit * 4;
                        int pickId = mainFrame.pickBuffer.get(idx + 3);
                       
                        if (pickId < 100) {
                                handler.mouseMode = handler.MOUSE_MANIP;
                                if (mainFrame.currentManip.axisMode != Manip.PICK_OTHER) // give
                                        // priority to
                                        // PICK_OTHER
                                        mainFrame.currentManip.setPickedInfo(pickId, camera, handler.lastMousePoint);
                                picked = true;
                        }
                }
                if (picked) {
                        if(mainFrame.currentManip instanceof RotateManip) {
                                ((RotateManip) (mainFrame.currentManip)).toggleCircleDepth();
                        }
                        mainFrame.refresh();
                        return;
                }
               
                // Then objects
                int closestZ = Integer.MAX_VALUE;
                int closestId = 0;
                for (int i_hit = 0; i_hit < numHits; i_hit++) {
                        int idx = i_hit * 4;

                        int pickId = mainFrame.pickBuffer.get(idx + 3);
                        if (pickId < 1000) {
                                break;
                        }
                        int pickZ = mainFrame.pickBuffer.get(idx+1);
                        picked = true;
                        if (pickZ < closestZ) {
                                closestZ = pickZ;
                                closestId = pickId;
                        } else continue;
                }
                if (picked) {
                        SceneNode t = Shape.get(closestId);
                        Shape s= Shape.get(closestId);
                        currentObjectId= closestId;
                        if(drawInPickVertMode){
                                Mesh m= s.mesh;
                                displayVerts(m);
                        }else{
                                if (t.getParent() != null) t=(SceneNode)t.getParent();
                                if (multiPickMode) transformationTreeView.addSelectionPath(new TreePath(t.getPath()));
                                else transformationTreeView.setSelectionPath(new TreePath(t.getPath()));
                        }
                       
                } else {
                        transformationTreeView.clearSelection();
                        if (mainFrame.currentManip != null) mainFrame.currentManip.drawEnabled = false;
                }
                refresh();
        }
        float[] verts;
        public void RenderVerts(Mesh m){
                GL gl = canvas.getGL();
               
                if(currentT != null){

                // current window transformation
                Vector3f translate= currentT.getTranslate();

                Vector3f scale= currentT.getScale();

                Vector3f rotate= currentT.getRotate();
                // current window transformation
               
                gl.glTranslatef(translate.x, translate.y, translate.z);
       
                gl.glRotatef(rotate.z, 0.0f, 0.0f, 1.0f);
                gl.glRotatef(rotate.y, 0.0f, 1.0f, 0.0f);
                gl.glRotatef(rotate.x, 1.0f, 0.0f, 0.0f);

                gl.glScalef(scale.x, scale.y, scale.z);
               
                }
                FloatBuffer nodes = m.getVerts();
                verts = new float[nodes.capacity()];
                for(int i = 0; i < nodes.capacity(); i++) {
                        verts[i] = nodes.get(i);
                }
               
               
                gl.glPointSize(5.0f);
                for(int i=0; i < m.getNumVertices(); i++) {
                        gl.glPushName(i);
                        gl.glBegin(GL.GL_POINTS);
                        gl.glVertex3f(verts[3*i], verts[3*i+1], verts[3*i+2]);
                        gl.glEnd();    
                        gl.glPopName();
                }// End of WHILE-LOOP
        }
       
        public static void resetVertexHitObjects() {
                currentVertex = null;
                currentVertexId = -1;
                drawInPickVertMode = false;
        }
       
        public void processVertHits(int hits, IntBuffer buffer, Mesh m) {
       
                int offset = 0;
                int names;
                float z1 = 0.0f;
                float z2 = 0.0f;
                for (int i = 0; i < hits; i++) {
                        names = buffer.get(offset);
                        offset++;      
                        z1 = (float) buffer.get(offset) / 0x7fffffff; // RED FLAG
                        offset++;
                        z2 = (float) buffer.get(offset) / 0x7fffffff;
                        offset++;
                        for (int j = 0; j < names; j++) {
                                if (j == (names - 1)) {
                                        FloatBuffer nodes = m.getVerts();
                                        // Set current vertex
                                        currentVertex = new Vector3f(nodes.get(3*buffer.get(offset)), nodes.get(3*buffer.get(offset)+1), nodes.get(3*buffer.get(offset)+2));
                                   
                                        // Set ID of current vertex
                                        currentVertexId = buffer.get(offset);
                                }
                                offset++;
                        }
                }
        }
       
        /**
         * Draws the object position grid
         */
        protected void drawGrid(GL gl) {
               
                int bigness = 10;
                gl.glPushAttrib(GL.GL_LIGHTING);
                gl.glDisable(GL.GL_LIGHTING);
                gl.glColor3f(0.4f, 0.4f, 0.4f);
                gl.glBegin(GL.GL_LINES);
                if (camera instanceof PerspectiveCamera) {
                        for (int i = -bigness; i <= bigness; i++) {
                                gl.glVertex3f(i, 0, -bigness);
                                gl.glVertex3f(i, 0, bigness);
                                gl.glVertex3f(-bigness, 0, i);
                                gl.glVertex3f(bigness, 0, i);
                        }
                }
                gl.glEnd();
                gl.glPopAttrib();
        }
       
        /**
         * @see javax.media.opengl.GLEventListener#reshape(javax.media.opengl.GLAutoDrawable, int, int, int, int)
         */
        public void reshape(GLAutoDrawable d, int x, int y, int width, int height) {
                axes = new GLAxes();
                camera.setAspect(((float) width) / height);
        }
       
        /**
         * Handles all mouse events in this window
         * @author arbree
         * Oct 21, 2005
         * GLView.java
         * Copyright 2005 Program of Computer Graphics, Cornell University
         */
        private class EventHandler extends MouseAdapter implements MouseMotionListener, ActionListener {
               
                Vector3f motion = new Vector3f();
                protected int lastMousePixel_X, lastMousePixel_Y;
                protected Vector2f lastMousePoint = new Vector2f();
                protected Vector2f currentMousePoint = new Vector2f();
                protected Vector2f mouseDelta = new Vector2f();
               
                //Mode constants
                protected final int MOUSE_PICK = 0;
                protected final int MOUSE_MANIP = 1;
                protected final int MOUSE_ORBIT = 61;
                protected final int MOUSE_ZOOM = 62;
                protected final int MOUSE_TRACK = 63;
                protected final int MOUSE_SPIN = 64;
               
                public int mouseMode = MOUSE_PICK;
               
                public void mouseClicked(MouseEvent e) {
     
                        if (e.getClickCount() == 2 && e.getSource() == canvas) {
                                mainFrame.setView(GLView.this);
        mainFrame.refresh();
                        }
                }
               
                /**
                 * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
                 */
                public void mousePressed(MouseEvent e) {
                       
                        lastMousePixel_X = e.getX();
                        lastMousePixel_Y = e.getY();
                        lastMousePoint.set(lastMousePixel_X, lastMousePixel_Y);
                        windowToViewport(lastMousePoint);
                        updateState(e);
                }
               
                /**
                 * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
                 */
                public void mouseReleased(MouseEvent e) {
                       
                        mouseMode = MOUSE_PICK;
                        if (mainFrame.currentManip != null)
                                mainFrame.currentManip.released();
                }
               
                /**
                 * Compute the current drawing state from the current mouse position
                 * @param e
                 */
                protected void updateState(MouseEvent e) {
                       
                        if (flagSet(e, MouseEvent.BUTTON1_DOWN_MASK) && !flagSet(e, MouseEvent.BUTTON3_DOWN_MASK) && !flagSet(e, MouseEvent.CTRL_DOWN_MASK) && flagSet(e, MouseEvent.ALT_DOWN_MASK)) {
                                mouseMode = MOUSE_ORBIT;
                        }
                        else if (!flagSet(e, MouseEvent.BUTTON1_DOWN_MASK) && flagSet(e, MouseEvent.BUTTON3_DOWN_MASK) && !flagSet(e, MouseEvent.CTRL_DOWN_MASK) && flagSet(e, MouseEvent.ALT_DOWN_MASK)) {
                                mouseMode = MOUSE_ZOOM;
                        }
                        else if (flagSet(e, MouseEvent.BUTTON1_DOWN_MASK) && !flagSet(e, MouseEvent.BUTTON3_DOWN_MASK) && flagSet(e, MouseEvent.CTRL_DOWN_MASK) && flagSet(e, MouseEvent.ALT_DOWN_MASK)) {
                                mouseMode = MOUSE_TRACK;
                        }
                        else if (flagSet(e, MouseEvent.BUTTON2_DOWN_MASK) && !flagSet(e, MouseEvent.BUTTON1_DOWN_MASK) && !flagSet(e, MouseEvent.BUTTON3_DOWN_MASK) && flagSet(e, MouseEvent.ALT_DOWN_MASK)) {
                                mouseMode = MOUSE_TRACK;
                        }
                        else if (!flagSet(e, MouseEvent.BUTTON1_DOWN_MASK) && flagSet(e, MouseEvent.BUTTON3_DOWN_MASK) && flagSet(e, MouseEvent.CTRL_DOWN_MASK) && flagSet(e, MouseEvent.ALT_DOWN_MASK)) {
                                mouseMode = MOUSE_SPIN;
                        }
                        else {
                                multiPickMode = flagSet(e, MouseEvent.SHIFT_DOWN_MASK);  
                                drawInPickMode = true;
                                refresh();
                        }
                }
               
                /**
                 * Compute viewport mouse positions from window position
                 * @param p
                 */
                protected void windowToViewport(Tuple2f p) {
                       
                        int w = canvas.getWidth();
                        int h = canvas.getHeight();
                        p.set((2 * p.x - w) / w, (2 * (h - p.y - 1) - h) / h);
                }
               
                /**
                 * Return the state of a mouse flag
                 * @param e
                 * @param flag
                 * @return
                 */
                protected boolean flagSet(MouseEvent e, int flag) {
                       
                        return (e.getModifiersEx() & flag) == flag;
                }
               
                private void modifyVertex() {
                       
                       
                       
                }
               
               
                /**
                 * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
                 */
                public void mouseDragged(MouseEvent e) {
                       
                        currentMousePoint.set(e.getX(), e.getY());
                        windowToViewport(currentMousePoint);
                       
                        //mouseDelta.sub(currentMousePoint, lastMousePoint);
                        mouseDelta.set(currentMousePoint);
                        mouseDelta.sub(lastMousePoint);
                       
                        switch (mouseMode) {
                        case MOUSE_PICK:
                                // don't support lasso-selection...
                                break;
                        case MOUSE_MANIP:
                                mainFrame.currentManip.dragged(currentMousePoint, mouseDelta );
                                break;
                        case MOUSE_TRACK:
                                camera.convertMotion(mouseDelta, motion);
                                mainFrame.trackAllCams(motion);
                                break;
                        case MOUSE_ORBIT:
                                if (camera == mainFrame.pViewCam)
                                        ((PerspectiveCamera) camera).orbit(mouseDelta);
                                else {
                                        camera.convertMotion(mouseDelta, motion);
                                        mainFrame.trackAllCams(motion);
                                }
                                break;
                        case MOUSE_ZOOM:
                                camera.zoom(mouseDelta.y);
                                break;
                        case MOUSE_SPIN:
                                break;
                        }
                       
                        lastMousePoint.set(e.getX(), e.getY());
                        windowToViewport(lastMousePoint);
                        mainFrame.refresh();
                }
               
                /**
                 * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
                 */
                public void mouseMoved(MouseEvent e) {
                       
                        // TODO: make sure nothing needs to be here
                }
               
                /**
                 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
                 */
                public void actionPerformed(ActionEvent e) {
                       
                        String cmd = e.getActionCommand();
                       
                        if (cmd == null) {
                                return;
                        }
                        else if (cmd.equals(WIREFRAME_CHECKBOX_TEXT)) {
                                wireframe = !wireframe;
                        }
                        else if (cmd.equals(LIGHTING_CHECKBOX_TEXT)) {
                                lighting = !lighting;
                        }
      else if (cmd.equals(FLIP_CHECKBOX_TEXT)) {
        camera.flip();
        canvas.display();
        canvas.display();
      }
                refresh();      
     
                }
        }
}

